#pragma once

#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <sys/msg.h>
#include "Log.hpp"

#define PATHNAME "./Queue"
#define PROID 123

#define CREATEMSGQUEUE (IPC_CREAT | IPC_EXCL | 0666)
#define GETMSGQUEUE (IPC_CREAT)

enum 
{
    SERVER_MSG_TYPE = 1,
    CLIENT_MSG_TYPE
}TYPE;

using namespace ns_log;

const int default_fd = -1;
const int default_size = 1024; // 1k
class MsgQueue
{
private:
    int _msgfd;
    struct msgbuf
    {
        long mtype;
        char mtext[default_size];
    };

public:
    MsgQueue() : _msgfd(default_fd)
    {
    }
    // 创建消息队列
    void Create(int flag)
    {
        // 1.先获取唯一key
        key_t key = ::ftok(PATHNAME, PROID);
        if (key == -1)
        {
            LOG(FATAL, "ftok错误,error : %s\n", strerror(errno));
            abort();
        }
        // 2.创建消息队列
        _msgfd = msgget(key, flag);
        if (_msgfd == -1)
        {
            LOG(FATAL, "创建消息队列失败\n");
            abort();
        }
        LOG(DEBUG, "创建消息队列完毕\n");
    }
    // 发送消息
    void Send(int type, const std::string &in)
    {
        struct msgbuf buf;
        memset(&buf, 0, sizeof(buf));
        // 1.拷贝
        buf.mtype = type;
        memcpy(buf.mtext, in.c_str(), in.size());
        // 2.发送
        int n = msgsnd(_msgfd, &buf, sizeof(buf.mtext), 0);
        if (n == -1)
        {
            LOG(ERROR, "发送消息失败\n");
            return;
        }
        LOG(DEBUG, "发送消息完毕\n");
    }
    //读取数据
    void Recv(int type, std::string *out)
    {
        struct msgbuf buf;
        
        int n = msgrcv(_msgfd,&buf,sizeof(buf.mtext),type,0);
        if(n == -1)
        {
            LOG(ERROR,"接收消息错误\n");
            return;
        }

        buf.mtext[n] = 0;
        *out = buf.mtext;
        LOG(DEBUG,"接收消息完毕\n");
    }
    void Destroy()
    {
        int n = msgctl(_msgfd, IPC_RMID, 0);
        if (n == -1)
        {
            LOG(FATAL, "销毁消息队列失败\n");
            abort();
        }
        LOG(DEBUG, "销毁消息队列完毕\n");
    }
    ~MsgQueue()
    {}
};

class Server : public MsgQueue
{
public:
    Server()
    {
        MsgQueue::Create(CREATEMSGQUEUE);
        LOG(DEBUG, "服务端创建完毕\n");
    }
    ~Server()
    {
        MsgQueue::Destroy();
    }
};

class Client : public MsgQueue
{

public:
    Client()
    {
        MsgQueue::Create(GETMSGQUEUE);
        LOG(DEBUG, "客户端创建完毕\n");
    }
    ~Client()
    {}
};
